package mop.model.task.tasktype;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

import mop.exception.IllegalDescriptionException;
import mop.exception.IllegalDuplicationException;
import mop.model.AbstractModel;
import mop.model.AbstractModelWithDescription;
import mop.model.DataBase;
import mop.model.ModelInterface;
import mop.model.resource.ResourceType;
import mop.model.task.Task;
import mop.model.task.field.Field;
import mop.model.task.field.FieldInterface;
import mop.model.user.User;
import mop.model.user.UserType;
import mop.util.Couple;

/**
 * TaskType class
 * 
 * @author MOP Team 7
 * 
 * @invar Description is valid.
 *  	  @see AbstractDescriptionModel
 */
public class TaskType extends AbstractModelWithDescription implements TaskTypeInterface
{

	/**
	 * Constructor for TaskType
	 * 
	 * @param db the instance of the database where our tasktypes are kept
	 * @param description the description of the tasktype
	 * @param fields the fields that the Tasktype has
	 * @param necessities the ResourceTypes this TaskType needs
	 * @param ownertypes the owner types for this Takstype
	 * 
	 * @effect	(Tries to) set the description.
	 * 			| setDescription(description)
	 * 
	 * @effect gets added to the database db
	 * 
	 * @throws  IllegalDescriptionException
	 * 			Thrown when the Project description is invalid.
	 * 
	 * @throws IllegalDuplicationException 
	 * 		| user might be duplicate
	 */
	public TaskType(DataBase<TaskType> db, String description,List<Field> fields,HashMap<ResourceType,Couple<Integer,Integer>> necessities,
			List<UserType> ownertypes) throws IllegalDescriptionException,IllegalDuplicationException
	{
		super(description);
		db.add(this);
		this.fields = fields;
		this.necessities = necessities;
		this.ownertypes = ownertypes;
	}
		
	
	
	/***************************************************************************
	 * 						Fields
	 ***************************************************************************/
	
	/**
	 * Clone all fields and return m
	 * 
	 * @return copy of fields list
	 */
	public List<Field> getFields()
	{
		if(this.fields == null) return null;
		LinkedList<Field> ret = new LinkedList<Field>();
		for(Field a : fields)
		{
			Field b = a.clone();
			ret.add(b);
		}
		return ret;
	}

        /**
         * Returns interfaces to copies of the fields.
         *
         * @return  List<FieldInterface>
         */
        public List<FieldInterface> getFieldList()
        {
            List<FieldInterface> f = new LinkedList<FieldInterface>();
            f.addAll(this.getFields());
            return f;
        }
	
	/** List containing fields */
	final List<Field> fields;
	
	
	/***************************************************************************
	 * 						ResourceTypes
	 ***************************************************************************/
	
	/**
	 * Forfills all the required resource constraints
	 * TODO update Task
	 * 
	 * @param t the task to be checked forfilling this tasktype
	 * 
	 * @return (t.getTasktype == this) && (t.getResources -> are ok for this.necessities)
	 */
	public boolean resourceConstraints(Task t)
	{
		return false;
	}
	
	final HashMap<ResourceType,Couple<Integer,Integer>> necessities;
	
	/***************************************************************************
	 * 						Owner Types
	 ***************************************************************************/
	
	/**
	 * Forfills all the required user constraints
	 * TODO update Task
	 * TODO update user
	 * 
	 * @param u the user that wants to create a task of this type
	 * 
	 * @return (list.has(u.getType())
	 */
	public boolean userConstraints(User u)
	{
		for(UserType o :ownertypes)
		{
			if(o.equals(u.getUserType())) return true;
		}
		return false;
	}
	
	/** owner types list */
	final List<UserType> ownertypes;
	
	
	
	
	/***************************************************************************
	 * 						Model interface
	 ***************************************************************************/
	
	/**
	 * @see ModelInterface#getId()
	 */
	public String getId() 
	{
		return getDescription();
	}
	
	/**
	 * get a reference to the interface
	 * @return this
	 */
	public TaskTypeInterface getInterface()
	{
		return this;
	}
	
	
}
